#include "musicplayer.h"
#include "ui_musicplayer.h"
#include <QPushButton>
#include <QMouseEvent>
#include <QDebug>
#include <QGraphicsDropShadowEffect>
#include <QJsonObject>
#include <QFileDialog>
#include <QDir>
#include <QMessageBox>
#include <QSqlError>
#include <QSqlQuery>
#include <QSystemTrayIcon>
#include <QMenu>

musicPlayer::musicPlayer(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::musicPlayer)
{
    ui->setupUi(this);

    //调用Init 完成初始化
    initUI();

    initSQLite();

    initPlayer();

    initMusicList();

    //关联信号和槽
    connectSignalAndSloats();

}

musicPlayer::~musicPlayer()
{
    delete ui;
}

//初始化工作
void musicPlayer::initUI()
{
    //添加系统托盘
    QSystemTrayIcon* trayIcon = new QSystemTrayIcon(this);
    trayIcon->setIcon(QIcon(":/images/tubiao.png"));

    //添加菜单
    QMenu* menu = new QMenu(this);
    menu->addAction("显示" , this , &QWidget::showNormal);
    menu->addAction("退出" , this , &musicPlayer::onMusicPlayerClose);

    trayIcon->setContextMenu(menu);
    trayIcon->show();

    //设置无边框
    this->setWindowFlags(Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint);

    //设置窗口背景为透明
    this->setAttribute(Qt::WA_TranslucentBackground);

    //设置图标
    this->setWindowIcon(QIcon(":/images/tubiao.png"));

    //设置阴影效果
    QGraphicsDropShadowEffect* shadowEffect = new QGraphicsDropShadowEffect(this);
    shadowEffect->setColor("#000000");  // 黑色
    shadowEffect->setOffset(0,0);
    shadowEffect->setBlurRadius(10);
    this->setGraphicsEffect(shadowEffect);

    //设置bodyLeft 图标和文字
    ui->rec->setbtIconAndText(":/images/rec.png" , "推荐" , 0);
    ui->radio->setbtIconAndText(":/images/radio.png" , "电台" , 1);
    ui->music->setbtIconAndText(":/images/music.png" , "音乐馆" , 2);
    ui->like->setbtIconAndText(":/images/like.png" , "我喜欢" , 3);
    ui->local->setbtIconAndText(":/images/local.png" , "本地下载" , 4);
    ui->recent->setbtIconAndText(":/images/recent.png" , "最近播放" , 5);

    //默认打开本地页面
    ui->stackedWidget->setCurrentIndex(4);
    curPage = ui->localPage;
    updateBtformAnimation();

    //初始化推荐页面
    srand(time(NULL));
    ui->recMusicBox->initRecBoxUi(RandomPicture() , 1);
    ui->supplyMusicBox->initRecBoxUi(RandomPicture() , 2);

    //设置CommanPage
    ui->likePage->setCommanPageUi("我喜欢" , ":/images/ilikebg.png");
    ui->localPage->setCommanPageUi("本地音乐" , ":/images/localbg.png");
    ui->recentPage->setCommanPageUi("最近播放" , ":/images/recentbg.png");

    //创建VolumeTool
    volumeTool = new VolumeTool(this);

    //设置play图标
    ui->play->setIcon(QIcon(":/images/play3.png"));

    //设置playMode图标 和 提示文字
    ui->playMode->setIcon(QIcon(":/images/list_play.png"));
    ui->playMode->setToolTip("列表循环");

    //创建LrcPage
    lrcPage = new LrcPage(this);
    lrcPage->hide();

    lrcPageAnimation = new QPropertyAnimation(lrcPage , "geometry" , this);
    lrcPageAnimation->setDuration(250);
    lrcPageAnimation->setStartValue(QRect(10 , 10 + lrcPage->height(), lrcPage->width() , lrcPage->height()));
    lrcPageAnimation->setEndValue(QRect(10 , 10 , lrcPage->width() , lrcPage->height()));
}

void musicPlayer::initPlayer()
{
    //创建
    player = new QMediaPlayer(this);
    playList = new QMediaPlaylist(this);

    //设置播放模式
    playList->setPlaybackMode(QMediaPlaylist::Loop);

    //列表添加到播放器
    player->setPlaylist(playList);

    //设置默认音量
    player->setVolume(20);
}

void musicPlayer::initSQLite()
{
    //添加数据库驱动
    sqlite = QSqlDatabase::addDatabase("QSQLITE");

    //命名
    sqlite.setDatabaseName("musicPlayer.db");

    //打开数据库
    if(!sqlite.open())
    {
        QMessageBox::critical(this , "打开数据库失败" , sqlite.lastError().text());
        return ;
    }
    qDebug() << "打开数据库";

    //创建表
    QString sql("create table if not exists musicInfo(\
                    id integer primary key autoincrement,\
                    musicid varchar(200) unique,\
                    musicName varchar(50),\
                    musicSigner varchar(50),\
                    albumName varchar(50),\
                    duration varchar(50),\
                    musicUrl bigint,\
                    isLike integer,\
                    isHistory integer)");
    QSqlQuery query;

    if(!query.exec(sql))
    {
        QMessageBox::critical(this , "数据库初始化失败" , query.lastError().text());
        return ;
    }
    qDebug() << "数据库初始化成功";

}

void musicPlayer::initMusicList()
{
    musicList.readFromDB();

    ui->likePage->setPageType(PageType::PAGE_LIKE);
    ui->likePage->reFresh(musicList);
    ui->localPage->setPageType(PageType::PAGE_LOCAL);
    ui->localPage->reFresh(musicList);
    ui->recentPage->setPageType(PageType::PAGE_HISTORY);

    ui->recentPage->reFresh(musicList);
}

QJsonArray musicPlayer::RandomPicture()
{
    QVector<QString> vecImageName;
    vecImageName<<"001.png"<<"003.png"<<"004.png"<<"005.png"<<"006.png"
                <<"007.png"<<"008.png"<<"009.png"<<"010.png"<<"011.png"
                <<"012.png"<<"013.png"<<"014.png"<<"015.png"<<"016.png"
                <<"017.png"<<"018.png"<<"019.png"<<"020.png"<<"021.png"
                <<"022.png"<<"023.png"<<"024.png"<<"025.png"<<"026.png"
                <<"027.png"<<"028.png"<<"029.png"<<"030.png"<<"031.png"
                <<"032.png"<<"033.png"<<"034.png"<<"035.png"<<"036.png"
                <<"037.png"<<"038.png"<<"039.png"<<"040.png";

    //随机函数
    std::random_shuffle(vecImageName.begin() , vecImageName.end());

    QJsonArray objArray;

    /*
        路径：:/images/rec/  + 00X.png
        文本：推荐- + 00X
    */

    for(int i = 0 ; i < vecImageName.size() ; ++i)
    {
        QJsonObject obj;
        //路径
        obj.insert("path" , ":/images/rec/" + vecImageName[i]);

        //文本
        QString strText =QString("推荐-%1").arg(i , 3, 10 , QChar('0'));
        obj.insert("text" , strText);

        objArray.append(obj);
    }

    return objArray;
}

void musicPlayer::mousePressEvent(QMouseEvent *event)
{
    if(event->buttons() == Qt::LeftButton)
    {
        isDrag = true;
        //获取鼠标和边框之间相对位置
        drawPoint = event->globalPos() - this->frameGeometry().topLeft();
        return ;
    }

    QWidget::mousePressEvent(event);
}

void musicPlayer::connectSignalAndSloats()
{
    //Btn(切换界面)
    connect(ui->rec , &BtForm::btClick , this , &musicPlayer::onBtFromClick);
    connect(ui->radio , &BtForm::btClick , this , &musicPlayer::onBtFromClick);
    connect(ui->music , &BtForm::btClick , this , &musicPlayer::onBtFromClick);
    connect(ui->like , &BtForm::btClick , this , &musicPlayer::onBtFromClick);
    connect(ui->local , &BtForm::btClick , this , &musicPlayer::onBtFromClick);
    connect(ui->recent , &BtForm::btClick , this , &musicPlayer::onBtFromClick);

    //收藏（喜欢）
    connect(ui->localPage , &CommanPage::updateLikeMusic , this , &musicPlayer::onUpdateLikeMusic);
    connect(ui->likePage , &CommanPage::updateLikeMusic , this , &musicPlayer::onUpdateLikeMusic);
    connect(ui->recentPage , &CommanPage::updateLikeMusic , this , &musicPlayer::onUpdateLikeMusic);

    /* ========================================================================================*/

    //音乐播放控制
    connect(ui->play , &QPushButton::clicked , this , &musicPlayer::onPlayMusic);
    connect(player , &QMediaPlayer::stateChanged , this , &musicPlayer::onPlayStateChanged);
    connect(ui->playPrev , &QPushButton::clicked , this , &musicPlayer::onPlayUpCliked);
    connect(ui->playNext , &QPushButton::clicked , this , &musicPlayer::onPlayDownCliked);
    connect(ui->playMode , &QPushButton::clicked , this , &musicPlayer::onPlayBackModeClicked);
    connect(playList , &QMediaPlaylist::playbackModeChanged , this , &musicPlayer::onPlayBackModeChanged);

    connect(ui->localPage , &CommanPage::playAll , this , &musicPlayer::onPlayAll);
    connect(ui->likePage , &CommanPage::playAll , this , &musicPlayer::onPlayAll);
    connect(ui->recentPage , &CommanPage::playAll , this , &musicPlayer::onPlayAll);

    connect(ui->localPage , &CommanPage::playMusicByIndex , this , &musicPlayer::onplayMusicByIndex);
    connect(ui->likePage , &CommanPage::playMusicByIndex , this , &musicPlayer::onplayMusicByIndex);
    connect(ui->recentPage , &CommanPage::playMusicByIndex , this , &musicPlayer::onplayMusicByIndex);

    connect(playList , &QMediaPlaylist::currentIndexChanged , this , &musicPlayer::onCurrentIndexChanged);

    connect(volumeTool , &VolumeTool::setSilence , this , &musicPlayer::setMusicSilence);

    connect(volumeTool , &VolumeTool::setMusicVolume , this , &musicPlayer::setPlayerVolume);

    connect(player , &QMediaPlayer::durationChanged , this , &musicPlayer::onDurationChanged);

    connect(player , &QMediaPlayer::positionChanged , this , &musicPlayer::onPositionChanged);

    connect(ui->processBar , &MusicSlider::setMusicSliderPosition , this , &musicPlayer::onMusicSliderChanged);

    connect(player, &QMediaPlayer::metaDataAvailableChanged , this , &musicPlayer::onMetaDataAvailableChanged);
}

void musicPlayer::mouseMoveEvent(QMouseEvent *event)
{
    if(event->buttons() == Qt::LeftButton && isDrag)
    {
        //当鼠标移动时，边框移动到鼠标相对位置之前。
        move(event->globalPos() - drawPoint);
        return ;
    }

    QWidget::mouseMoveEvent(event);
}



void musicPlayer::on_quit_clicked()
{
    hide();
}

void musicPlayer::onBtFromClick(int pageid)
{
    //其他的自定义控件都在musicPlayer里，自定义控件无法修改，因此通过信号和槽机制，通过槽函数来完成
    QList<BtForm*> btFormList = QObject::findChildren<BtForm*>();
    for(auto btForm : btFormList)
    {
        if(btForm->Pageid() != pageid)
        {
            btForm->clearBackground();
        }
    }

    isDrag = false;

    ui->stackedWidget->setCurrentIndex(pageid);

}

void musicPlayer::on_volume_clicked()
{
    //设置volume空间坐标为全局坐标，并获取volume坐标
    QPoint point = ui->volume->mapToGlobal(QPoint(0,0));

    //计算volumeTool坐标 即point左上角
    QPoint volumeToolLeftTop =point - QPoint(volumeTool->width() - 64 , volumeTool->height() - 28);

    //移动volumeTool
    volumeTool->move(volumeToolLeftTop);

    //显示volumeTool
    volumeTool->show();
}

void musicPlayer::on_addLocal_clicked()
{
    //创建FileDialog窗口
    QFileDialog* fileDialog = new QFileDialog(this);

    //设置窗口标题
    fileDialog->setWindowTitle("添加本地下载音乐");

    //设置打开目录
    QDir defDir(QDir::currentPath());
    defDir.cdUp();
    QString musicDir =defDir.path() + "/MusicPlayer/musics";
    fileDialog->setDirectory(musicDir);

    //设置打开文件数量: 一次可以打开多个文件
    fileDialog->setFileMode(QFileDialog::ExistingFiles);

    //设置窗口类型: 打开窗口
    fileDialog->setAcceptMode(QFileDialog::AcceptOpen);

    //设置文件过滤器
    QStringList suffixList;
    suffixList << "所有文件(*)"<< "代码文件(*.h .c *.hpp *.cpp)" << "图片文件(*.jpeg *.jpeg *.png)" << "音乐文件(*.mpr *.lrc)" ;
    fileDialog->setNameFilters(suffixList);

    //显示 并 获取打开的文件的路径
    if(fileDialog->exec() == QFileDialog::Accepted)
    {
        //打开本地音乐下载Page
        ui->stackedWidget->setCurrentIndex(4);

        QList<QUrl> urls = fileDialog->selectedUrls();

        //添加音乐Music 到 MusicList
        musicList.addMusicByUrl(urls);

        //添加音乐到各个Page中
        ui->localPage->reFresh(musicList);

        //本地音乐添加到playList中
        ui->localPage->addMusicToPlayer(musicList , playList);
    }


}

void musicPlayer::onUpdateLikeMusic(bool isLike, QString musicId)
{
    auto it = musicList.findMusicById(musicId);
    if(it != musicList.end())
    {
        it->setIsLike(isLike);
    }
    ui->localPage->reFresh(musicList);
    ui->likePage->reFresh(musicList);
    ui->recentPage->reFresh(musicList);
}

void musicPlayer::onPlayMusic()
{
    // 播放和暂停
    if(player->state() == QMediaPlayer::StoppedState)
    {
        player->play();
    }
    else if(player->state() == QMediaPlayer::PausedState)
    {
        player->play();
    }
    else if(player->state() == QMediaPlayer::PlayingState)
    {
        player->pause();
    }
    else
    {
        qDebug() << player->errorString();
    }
}

void musicPlayer::onPlayStateChanged()
{
    if(player->state() == QMediaPlayer::PlayingState)
    {
        ui->play->setIcon(QIcon(":/images/play_on.png"));
    }
    else
    {
        ui->play->setIcon(QIcon(":/images/play3.png"));
    }
}

void musicPlayer::onPlayUpCliked()
{
    playList->previous();
}

void musicPlayer::onPlayDownCliked()
{
    playList->next();
}

void musicPlayer::onPlayBackModeClicked()
{
    //列表循环  -->  随机循环  -->  单曲循环  -->  列表循环...
    if(playList->playbackMode() == QMediaPlaylist::Loop)
    {
        playList->setPlaybackMode(QMediaPlaylist::Random);
        ui->playMode->setToolTip("随机循环");
    }
    else if(playList->playbackMode() == QMediaPlaylist::Random)
    {
         playList->setPlaybackMode(QMediaPlaylist::CurrentItemOnce);
         ui->playMode->setToolTip("单曲循环");
    }
    else if(playList->playbackMode() == QMediaPlaylist::CurrentItemOnce)
    {
         playList->setPlaybackMode(QMediaPlaylist::Loop);
         ui->playMode->setToolTip("列表循环");
    }
    else
    {
        qDebug() << "暂不支持";
    }
}

void musicPlayer::onPlayBackModeChanged(QMediaPlaylist::PlaybackMode mode)
{
    if(mode == QMediaPlaylist::Loop)
    {
        ui->playMode->setIcon(QIcon(":/images/list_play.png"));
    }
    else if(mode == QMediaPlaylist::Random)
    {
        ui->playMode->setIcon(QIcon(":/images/shuffle_2.png"));
    }
    else if(mode == QMediaPlaylist::CurrentItemOnce)
    {
        ui->playMode->setIcon(QIcon(":/images/single_play.png"));
    }
    else
    {
        qDebug() << "暂不支持";
    }
}

void musicPlayer::onPlayAll(PageType pageType)
{
    CommanPage* page = nullptr;
    switch(pageType)
    {
    case PAGE_LIKE:
        page = ui->likePage;
        break;
    case PAGE_LOCAL:
        page = ui->localPage;
        break;
    case PAGE_HISTORY:
        page = ui->recentPage;
        break;
    }

    playAllOfCommonPage(page , 0);
}

void musicPlayer::onplayMusicByIndex(CommanPage *page, int index)
{
    playAllOfCommonPage(page , index);
}

void musicPlayer::playAllOfCommonPage(CommanPage *page, int index)
{
    curPage = page;
    updateBtformAnimation();

    // 播放page所在⻚⾯的⾳乐
    // 将播放列表先清空，否则⽆法播放当前CommonPage⻚⾯的歌曲
    // 另外：该⻚⾯⾳乐不⼀定就在播放列表中，因此需要先将该⻚⾯⾳乐添加到播放列表
    playList->clear();

    // 将当前⻚⾯歌曲添加到播放列表
    page->addMusicToPlayer(musicList , playList);

    // 设置当前播放列表的索引
    playList->setCurrentIndex(index);

    player->play();
    onMetaDataAvailableChanged(true);
}

void musicPlayer::updateBtformAnimation()
{
    int index = ui->stackedWidget->indexOf(curPage);
    if(index == -1)
    {
        qDebug() << "该页面不存在";
        return ;
    }
    QList<BtForm*> btForms = this->findChildren<BtForm*>();
    for(auto btForm : btForms)
    {
        if(btForm->Pageid() == index)
            btForm->showAnimation(true);
        else
            btForm->showAnimation(false);
    }
}


void musicPlayer::onCurrentIndexChanged(int index)
{
    currentIndex = index;

    QString musicId = curPage->getMusicIdByIndex(index);
    auto it = musicList.findMusicById(musicId);
    if(it != musicList.end())
    {
        // 将该⾳乐设置为历史播放记录
        it->setIsHistory(true);
    }

    ui->recentPage->reFresh(musicList);
}

void musicPlayer::setMusicSilence(bool isMuted)
{
    player->setMuted(isMuted);
}

void musicPlayer::setPlayerVolume(int volumeRatio)
{
    player->setVolume(volumeRatio);
}

void musicPlayer::onDurationChanged(qint64 duration)
{
    total = duration;
    ui->totalTime->setText(QString("%1:%2").arg(duration / 1000 / 60 , 2 , 10 , QChar('0'))
                           .arg(duration / 1000 % 60 , 2 , 10 , QChar('0')));
}

void musicPlayer::onPositionChanged(qint64 position)
{
    ui->currentTime->setText(QString("%1:%2").arg(position / 1000 / 60 , 2 , 10 , QChar('0'))
                             .arg(position / 1000 % 60 , 2 , 10 , QChar('0')));

    //同步到进度条
    ui->processBar->setStep(position / (float)total);

    //同步歌词界面
    if(currentIndex >= 0)
        lrcPage->showLrcWord(position);
}

void musicPlayer::onMusicSliderChanged(float ratio)
{
    qint64 position = total * ratio;
    ui->currentTime->setText(QString("%1:%2").arg(position / 1000 / 60 , 2 , 10 , QChar('0'))
                             .arg(position / 1000 % 60 , 2 , 10 , QChar('0')));

    player->setPosition(position);
}

void musicPlayer::onMetaDataAvailableChanged(bool available)
{
    (void)available;
    qDebug() << "yes";
    QString musicId = curPage->getMusicIdByIndex(currentIndex);

    auto it = musicList.findMusicById(musicId);

    QString musicName = "歌曲未知";
    QString signerName = "歌手未知";
    if(it != musicList.end())
    {
        musicName = it->getMusicName();
        signerName = it->getSignerName();
    }
    ui->musicName->setText(musicName);
    ui->musicSigner->setText(signerName);

    QVariant coverImage = player->metaData("ThumbnailImage");
    if(coverImage.isValid())
    {
        QImage image = coverImage.value<QImage>();

        ui->musicCover->setPixmap(QPixmap::fromImage(image));
        curPage->setMusicImage(QPixmap::fromImage(image));
    }
    else
    {
        qDebug() << "歌曲没有封面图片";
        QString path = ":/images/tubiao.png";
        ui->musicCover->setPixmap(path);
        curPage->setMusicImage(path);
    }
    ui->musicCover->setScaledContents(true);

    //改变歌曲歌词
    if(it != musicList.end())
    {
        QString lrcFilepath = it->getLrcFilePath();
        lrcPage->parseLrc(lrcFilepath);
    }

}

void musicPlayer::on_lrcWord_clicked()
{
    lrcPage->show();
    lrcPageAnimation->start();
}

void musicPlayer::on_skin_clicked()
{
    QMessageBox::critical(this , "换肤" , "暂不支持此功能，正在研发ing ...");
}

void musicPlayer::on_min_clicked()
{
    showMinimized();
}

void musicPlayer::on_max_clicked()
{
    showMaximized();
}

void musicPlayer::onMusicPlayerClose()
{
    //加载music信息到SQL中
    musicList.writeToDB();

    //关闭SQL连接
    sqlite.close();

    //关闭窗口
    this->close();
}
